/*
 * Copyright (C) 2025 SDFX Project
 * SDFX is licensed under Mulan PSL v2.
 */

/**
 * @file protocol.h
 * @brief SDFX protocol definitions
 */

#ifndef SDFX_PROTOCOL_H
#define SDFX_PROTOCOL_H

#include "sdf_types.h"
#include "sdfx_defaults.h"
#include <arpa/inet.h>

#ifdef __cplusplus
extern "C" {
#endif

/* protocol magic number */
#define SDFX_PROTOCOL_MAGIC     0x53444658  /* "SDFX" */
#define SDFX_MAGIC              SDFX_PROTOCOL_MAGIC

/* protocol version */
#define SDFX_PROTOCOL_VERSION   0x00010000  /* 1.0.0 */

/* Network configuration - use unified default configuration */
/* SDFX_DEFAULT_PORT is now defined in common/include/sdfx_defaults.h */

/* Limit constants */
#define SDFX_MAX_RANDOM_LENGTH  65536

/* Message type definitions */
#define SDFX_CMD_OPEN_DEVICE            0x0001
#define SDFX_CMD_CLOSE_DEVICE           0x0002
#define SDFX_CMD_OPEN_SESSION           0x0003
#define SDFX_CMD_CLOSE_SESSION          0x0004
#define SDFX_CMD_GET_DEVICE_INFO        0x0005
#define SDFX_CMD_GENERATE_RANDOM        0x0006
#define SDFX_CMD_HASH_INIT              0x0010
#define SDFX_CMD_HASH_UPDATE            0x0011
#define SDFX_CMD_HASH_FINAL             0x0012
#define SDFX_CMD_ENCRYPT                0x0020
#define SDFX_CMD_DECRYPT                0x0021
#define SDFX_CMD_INTERNAL_SIGN_ECC      0x0030
#define SDFX_CMD_INTERNAL_VERIFY_ECC    0x0031
#define SDFX_CMD_EXTERNAL_ENCRYPT_ECC   0x0032
#define SDFX_CMD_EXTERNAL_DECRYPT_ECC   0x0033
#define SDFX_CMD_GENERATE_KEYPAIR_ECC   0x0034
#define SDFX_CMD_EXTERNAL_SIGN_ECC      0x0035
#define SDFX_CMD_EXTERNAL_VERIFY_ECC    0x0036

/* Message header structure */
typedef struct sdfx_message_header {
    ULONG magic;        /* protocol magic number */
    ULONG version;      /* protocol version */
    ULONG cmd;          /* command type */
    ULONG length;       /* data length */
    ULONG session_id;   /* session ID */
    ULONG status;       /* status code */
    ULONG reserved[2];  /* reserved field */
} sdfx_message_header_t;

/* Complete message structure */
typedef struct sdfx_message {
    sdfx_message_header_t header;
    BYTE data[0];       /* variable length data */
} sdfx_message_t;

/* Message header size */
#define SDFX_MESSAGE_HEADER_SIZE    sizeof(sdfx_message_header_t)

/* Maximum message size */
#define SDFX_MAX_MESSAGE_SIZE       (64 * 1024)  /* 64KB */

/* Various request/response data structures */

/* Open device request */
typedef struct sdfx_open_device_req {
    ULONG device_type;      /* device type */
    BYTE reserved[16];      /* reserved */
} sdfx_open_device_req_t;

/* Open device response */
typedef struct sdfx_open_device_resp {
    HANDLE device_handle;   /* device handle */
} sdfx_open_device_resp_t;

/* Close device request */
typedef struct sdfx_close_device_req {
    HANDLE device_handle;   /* device handle */
} sdfx_close_device_req_t;

/* Close device response */
typedef struct sdfx_close_device_resp {
    BYTE reserved[4];       /* reserved field */
} sdfx_close_device_resp_t;

/* Open session request */
typedef struct sdfx_open_session_req {
    HANDLE device_handle;   /* device handle */
} sdfx_open_session_req_t;

/* Open session response */
typedef struct sdfx_open_session_resp {
    HANDLE session_handle;  /* session handle */
} sdfx_open_session_resp_t;

/* Close session request */
typedef struct sdfx_close_session_req {
    HANDLE session_handle;  /* session handle */
} sdfx_close_session_req_t;

/* Close session response */
typedef struct sdfx_close_session_resp {
    BYTE reserved[4];       /* reserved field */
} sdfx_close_session_resp_t;

/* Get device info request */
typedef struct sdfx_get_device_info_req {
    HANDLE session_handle;  /* session handle */
} sdfx_get_device_info_req_t;

/* Get device info response */
typedef struct sdfx_get_device_info_resp {
    DEVICEINFO device_info; /* device information */
} sdfx_get_device_info_resp_t;

/* Generate random number request */
typedef struct sdfx_generate_random_req {
    HANDLE session_handle;  /* session handle */
    ULONG length;          /* random number length */
} sdfx_generate_random_req_t;

/* Generate random number response */
typedef struct sdfx_generate_random_resp {
    ULONG length;          /* actual random number length */
    BYTE random_data[0];   /* random number data */
} sdfx_generate_random_resp_t;

/* Hash initialize request */
typedef struct sdfx_hash_init_req {
    HANDLE session_handle;     /* session handle */
    ULONG alg_id;             /* algorithm ID */
    ECCrefPublicKey public_key; /* SM2 public key (optional) */
    ULONG id_length;          /* ID length */
    BYTE id_data[0];          /* ID data */
} sdfx_hash_init_req_t;

/* Hash initialize response */
typedef struct sdfx_hash_init_resp {
    /* No response data */
} sdfx_hash_init_resp_t;

/* Hash update request */
typedef struct sdfx_hash_update_req {
    HANDLE session_handle;  /* session handle */
    ULONG data_length;     /* data length */
    BYTE data[0];          /* data to be hashed */
} sdfx_hash_update_req_t;

/* Hash update response */
typedef struct sdfx_hash_update_resp {
    /* No response data */
} sdfx_hash_update_resp_t;

/* Hash final request */
typedef struct sdfx_hash_final_req {
    HANDLE session_handle;  /* session handle */
} sdfx_hash_final_req_t;

/* Hash final response */
typedef struct sdfx_hash_final_resp {
    ULONG hash_length;     /* hash value length */
    BYTE hash_data[0];     /* hash value data */
} sdfx_hash_final_resp_t;

/* Encrypt request */
typedef struct sdfx_encrypt_req {
    HANDLE session_handle;  /* session handle */
    HANDLE key_handle;      /* key handle */
    ULONG alg_id;          /* algorithm ID */
    ULONG iv_length;       /* IV length */
    ULONG data_length;     /* data length */
    BYTE payload[0];       /* IV + data */
} sdfx_encrypt_req_t;

/* Encrypt response */
typedef struct sdfx_encrypt_resp {
    ULONG enc_data_length; /* ciphertext length */
    BYTE enc_data[0];      /* ciphertext data */
} sdfx_encrypt_resp_t;

/* Decrypt request */
typedef struct sdfx_decrypt_req {
    HANDLE session_handle;  /* session handle */
    HANDLE key_handle;      /* key handle */
    ULONG alg_id;          /* algorithm ID */
    ULONG iv_length;       /* IV length */
    ULONG enc_data_length; /* ciphertext length */
    BYTE payload[0];       /* IV + ciphertext */
} sdfx_decrypt_req_t;

/* Decrypt response */
typedef struct sdfx_decrypt_resp {
    ULONG data_length;     /* plaintext length */
    BYTE data[0];          /* plaintext data */
} sdfx_decrypt_resp_t;

/* ECC internal sign request */
typedef struct sdfx_internal_sign_ecc_req {
    HANDLE session_handle;  /* session handle */
    ULONG key_index;       /* private key index */
    ULONG data_length;     /* data length */
    BYTE data[0];          /* data to be signed */
} sdfx_internal_sign_ecc_req_t;

/* ECC internal sign response */
typedef struct sdfx_internal_sign_ecc_resp {
    ECCSignature signature; /* signature value */
} sdfx_internal_sign_ecc_resp_t;

/* ECC internal verify request */
typedef struct sdfx_internal_verify_ecc_req {
    HANDLE session_handle;  /* session handle */
    ULONG key_index;       /* public key index */
    ULONG data_length;     /* data length */
    ECCSignature signature; /* signature value */
    BYTE data[0];          /* data to be verified */
} sdfx_internal_verify_ecc_req_t;

/* ECC external encrypt request */
typedef struct sdfx_external_encrypt_ecc_req {
    HANDLE session_handle;     /* session handle */
    ULONG alg_id;             /* algorithm ID */
    ECCrefPublicKey public_key; /* public key */
    ULONG data_length;        /* data length */
    BYTE data[0];             /* data to be encrypted */
} sdfx_external_encrypt_ecc_req_t;

/* ECC external encrypt response */
typedef struct sdfx_external_encrypt_ecc_resp {
    ECCCipher cipher;         /* ciphertext */
} sdfx_external_encrypt_ecc_resp_t;

/* ECC external decrypt request */
typedef struct sdfx_external_decrypt_ecc_req {
    HANDLE session_handle;       /* session handle */
    ULONG alg_id;               /* algorithm ID */
    ECCrefPrivateKey private_key; /* private key */
    ECCCipher cipher;           /* ciphertext */
} sdfx_external_decrypt_ecc_req_t;

/* ECC external decrypt response */
typedef struct sdfx_external_decrypt_ecc_resp {
    ULONG data_length;         /* plaintext length */
    BYTE data[0];              /* plaintext data */
} sdfx_external_decrypt_ecc_resp_t;

/* ECC key pair generate request */
typedef struct sdfx_generate_keypair_ecc_req {
    HANDLE session_handle;     /* session handle */
    ULONG alg_id;             /* algorithm ID (SGD_SM2_1) */
} sdfx_generate_keypair_ecc_req_t;

/* ECC key pair generate response */
typedef struct sdfx_generate_keypair_ecc_resp {
    ECCrefPublicKey public_key;   /* Generated public key */
    ECCrefPrivateKey private_key; /* Generated private key */
} sdfx_generate_keypair_ecc_resp_t;

/* ECC external sign request */
typedef struct sdfx_external_sign_ecc_req {
    HANDLE session_handle;       /* session handle */
    ULONG alg_id;               /* algorithm ID */
    ECCrefPrivateKey private_key; /* private key */
    ULONG data_length;          /* data length */
    BYTE data[0];               /* data to be signed */
} sdfx_external_sign_ecc_req_t;

/* ECC external sign response */
typedef struct sdfx_external_sign_ecc_resp {
    ULONG signature_length;     /* signature length */
    BYTE signature[0];          /* signature data */
} sdfx_external_sign_ecc_resp_t;

/* ECC external verify request */
typedef struct sdfx_external_verify_ecc_req {
    HANDLE session_handle;      /* session handle */
    ULONG alg_id;              /* algorithm ID */
    ECCrefPublicKey public_key; /* public key */
    ULONG data_length;         /* data length */
    ULONG signature_length;    /* signature length */
    BYTE payload[0];           /* data + signature */
} sdfx_external_verify_ecc_req_t;

/* ECC external verify response */
typedef struct sdfx_external_verify_ecc_resp {
    ULONG result;              /* verify result (0=success) */
} sdfx_external_verify_ecc_resp_t;

/**
 * @brief Create message
 * @param cmd Command type
 * @param session_id Session ID
 * @param data Data pointer
 * @param data_len Data length
 * @param msg_len Returns the total message length
 * @return Message pointer, needs to be freed by the caller
 */
sdfx_message_t* sdfx_message_create(ULONG cmd, ULONG session_id, 
                                   const void *data, ULONG data_len, 
                                   ULONG *msg_len);

/**
 * @brief Destroy message
 * @param msg Message pointer
 */
void sdfx_message_destroy(sdfx_message_t *msg);

/**
 * @brief Validate message header
 * @param header Message header pointer
 * @return 0 for success, non-zero for failure
 */
int sdfx_message_validate_header(const sdfx_message_header_t *header);

/**
 * @brief Serialize message header to network byte order
 * @param header Message header pointer
 */
void sdfx_message_header_to_network(sdfx_message_header_t *header);

/**
 * @brief Deserialize message header from network byte order
 * @param header Message header pointer
 */
void sdfx_message_header_from_network(sdfx_message_header_t *header);

/**
 * @brief Byte order conversion functions
 */
static inline ULONG sdfx_htonl(ULONG hostlong) {
    return htonl(hostlong);  /* Use network byte order consistently */
}

static inline ULONG sdfx_ntohl(ULONG netlong) {
    return ntohl(netlong);   /* Use network byte order consistently */
}

#ifdef __cplusplus
}
#endif

#endif /* SDFX_PROTOCOL_H */